1.引入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
|
2.注入对象ServerEndpointExporter
@Configuration public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }
|
3.WebSocket 具体实现类
package com.example.springbootwebsocket.mysocket; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.stereotype.Component; import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CopyOnWriteArraySet;
@ServerEndpoint(value="/websocket/{nickname}") @Component public class MyWebSocket { private static CopyOnWriteArraySet<MyWebSocket> webSocketSet = new CopyOnWriteArraySet<MyWebSocket>(); private static Map<String,Session> map = new HashMap<String,Session>(); private Session session; private String nickname;
@OnOpen public void onOpen(Session session,@PathParam("nickname") String nickname){ this.session = session; this.nickname = nickname; map.put(session.getId(), session); webSocketSet.add(this); this.session.getAsyncRemote().sendText(nickname+"上线了,(我的id号是"+session.getId()+")"); }
@OnClose public void onClose(Session session){ webSocketSet.remove(this); map.remove(session.getId()); }
@OnMessage public void onMessage(String message,Session session,@PathParam("nickname") String nickname){ try { SocketMsg socketMsg = new ObjectMapper().readValue(message, SocketMsg.class); if(socketMsg.getType() == 1){ socketMsg.setFromUser(session.getId()); Session fromSession = map.get(socketMsg.getFromUser()); Session toSession = map.get(socketMsg.getToUser()); if(toSession != null){ fromSession.getAsyncRemote().sendText(nickname+":"+socketMsg.getMsg()); toSession.getAsyncRemote().sendText(nickname+":"+socketMsg.getMsg()); }else{ fromSession.getAsyncRemote().sendText("系统消息:对方不在线或者您输入的id号有误"); } }else { broadcast(socketMsg,nickname); } } catch (JsonParseException e) { e.printStackTrace(); } catch (JsonMappingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
public void onError(Session session,Throwable error){ System.out.println("发生错误"); error.printStackTrace(); }
private void broadcast(SocketMsg socketMsg ,String nickname){ for(MyWebSocket item:webSocketSet){ item.session.getAsyncRemote().sendText(nickname+":"+socketMsg.getMsg()); } } }
|
4.创建消息对象SocketMsg
package com.example.springbootwebsocket.mysocket; public class SocketMsg { private int type; private String fromUser; private String toUser; private String msg; public int getType() { return type; } public void setType(int type) { this.type = type; } public String getFromUser() { return fromUser; } public void setFromUser(String fromUser) { this.fromUser = fromUser; } public String getToUser() { return toUser; } public void setToUser(String toUser) { this.toUser = toUser; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } }
|
5.static目录下创建客户端 webSocketTest.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>聊天室</title> <style> #message{ margin-top:20px; border:1px solid gray; padding:20px; } </style> </head> <body> 昵称:<input type="text" id="nickname" /> <button onclick="conectWebSocket()">连接服务器</button> <button onclick="closeWebSocket()">断开连接</button> <br /> 消息:<input id="text" type="text" /> id号<input id="toUser" type="text" /> <button onclick="send()">发送消息</button>
<div id="message"> </div> <script type="text/javascript"> var websocket = null; var nickname = null; function conectWebSocket(){ nickname = document.getElementById("nickname").value; if(nickname == ''){ alert("请输入昵称"); return; } if("WebSocket" in window){ websocket = new WebSocket("ws://localhost:8080/websocket/"+nickname); }else{ alert("Not support websocket"); return false; } websocket.onopen = function(event){ setMessgeHtml("Loc MSG:连接成功"); } websocket.onclose = function(event){ setMessgeHtml("Loc MSG:连接关闭"); } websocket.onerror = function(event){ setMessgeHtml("Loc MSG:连接异常"); } websocket.onmessage = function(event){ setMessgeHtml(event.data); } } function setMessgeHtml(msg){ var message = document.getElementById("message"); message.innerHTML += msg+"<br/>"; }
function send(){ var message = document.getElementById("text").value; var toUser = document.getElementById("toUser").value; var socketMsg = {msg:message,toUser:toUser}; if(toUser == ''){ socketMsg.type =0; }else{ socketMsg.type =1; } websocket.send(JSON.stringify(socketMsg)); } </script> </body> </html>
|
测试,打开多个登录窗口,输入http://127.0.0.1:8080/webSocketTest.html ,输入昵称点击连接即可登录成功,群聊直接发送消息即可,私聊输入完消息后,选择对应那个人的id号码就行,快去试试吧:

总结:了解了websocket底层是怎么实现的,websocket协议稍微麻烦,其实我们完全可以用它的子协议STOMP来实现本文所有的功能,因已封装的很好,用起来非常简单,实例:SpringBoot+STOMP 实现聊天室(单聊+多聊)及群发消息详解。
参考:https://www.iteye.com/blog/412887952-qq-com-2405514